package Thread;

//"懒汉模式"的方式实现单例模式（线程不安全）
//创建实例的时间比较晚，只到第一次使用的时候才会创建实例
class SingletonLazy{
    //这个引用指向唯一实例，这个引用先初始化为null，而不是立即创建实例
    private static SingletonLazy instance=null;
    private static Object locker=new Object();
    public static SingletonLazy getInstance(){
        //rugninstance为null,说明是首次调用，首次调用要考虑线程安全问题，就要加锁
        //如果非null，就说明是后续的调用，就不必加锁了
        //双重校验锁
        if(instance==null){
            //如果首次调用getInstance，那么此时instance引用为空，就会进入if条件，从而把实例创建出来
            //如果是后续再次调用getInstance，由于instance已经不再是null了，此时不会进入if，直接返回之前创建好的引用了
            //这样设定，仍然可以保证该类的实例是唯一一个
            //与此同时，创建实例的时机就不是程序驱动时了，而是第一次调用getInstance的时候
            synchronized (locker){
                if(instance==null){
                    instance=new SingletonLazy();
                }
            }
        }
        return instance;

    }
    private SingletonLazy(){}
}
public class ThreadDemo23 {
    public static void main(String[] args) {
        SingletonLazy s1=SingletonLazy.getInstance();
        SingletonLazy s2=SingletonLazy.getInstance();
        System.out.println(s1==s2);//true,指向同一个实例
    }
}

//在”懒汉模式“代码中，有读也有写，读是if条件判断和return语句，写是 instance=new SingletonLazy();
//怎样让线程安全？加锁，把synchronized套到if外面，把if和new打包成原子的


//上述代码仍有一点问题，就是指令重排序引起的线程安全问题
//指令重排序也是编译器优化的一种方式，通过调整原有代码的执行顺序，保证逻辑不变的前提下，提供程序的效率